Dart _fe_analyzer_shared scanner AbstractScanner tokenize
tokenize 主要任务是将输入的源代码转换为一个词素流,AbstractScanner 类最核心方法。
调用处
全局搜索调用 tokenize() 的地方,就能知道全局在哪里启动了编译的初步流程。
- pkg\analysis_server\lib\src\lsp\source_edits.dart
- pkg\analysis_server\lib\src\services\correction\statement_analyzer.dart
- pkg\analysis_server\lib\src\services\correction\util.dart
- pkg\analyzer\lib\dart\analysis\utilities.dart
- pkg\analyzer\lib\src\fasta\doc_comment_builder.dart
- pkg\front_end\lib\src\fasta\util\parser_ast.dart- fasta 的 genAST 方法中调用
- 此处值得注意
 
- pkg\front_end\lib\src\fasta\util\textual_outline.dart
- pkg\front_end\tool\dart_doctest_impl.dart
- pkg\front_end\tool\duplicate_code_finder_experiment.dart
- pkg\front_end\tool\_fasta\parser_ast_helper_creator.dart
- pkg\scrape\lib\scrape.dart
以上代码中,省略了各个 test 目录下的代码。
代码实现
@override
Token tokenize() {
  // 首先,它进入一个循环
  // 只要没有到达文件的末尾,就会继续执行循环。
  while (!atEndOfFile()) {
	// 在每次循环中,它首先调用 
	// `advance` 方法来获取下一个字符。
    int next = advance();
	// 然后,它会检查是否已经读取到文件的末尾。
    // Scan the header looking for a language version
    if (!identical(next, $EOF)) {
      // 如果没有
      Token oldTail = tail;
      // 它会调用 `bigHeaderSwitch` 方法
      // 来处理文件头部的语言版本信息。
      next = bigHeaderSwitch(next);
      // 如果读取到的字符是脚本词素
      if (!identical(next, $EOF) && tail.kind == SCRIPT_TOKEN) {
        // 它会再次调用 `bigHeaderSwitch` 方法。
        oldTail = tail;
        next = bigHeaderSwitch(next);
      }
      // 然后,只要没有读取到文件的末尾,并且最后一个词素没有改变,
      // 它会继续调用 `bigHeaderSwitch` 方法。
      while (!identical(next, $EOF) && tail == oldTail) {
        next = bigHeaderSwitch(next);
      }
      next = next;
    }
	// 接下来,只要没有读取到文件的末尾
	// 它会调用 `bigSwitch` 方法来处理剩余的字符。
    while (!identical(next, $EOF)) {
      next = bigSwitch(next);
    }
    // 如果已经读取到文件的末尾
    // 它会调用 `appendEofToken` 方法
    // 来添加一个表示文件结束的词素。
    if (atEndOfFile()) {
      appendEofToken();
    } else {
      // 否则,它会调用 `unexpectedEof` 方法
      // 来处理意外的文件结束。
      unexpectedEof();
    }
  }
  // 在循环结束后,它会将字符串偏移量加一并添加到行开始的列表中,
  // 这是为了模拟文件末尾的行。
  // Always pretend that there's a line at the end of the file.
  lineStarts.add(stringOffset + 1);
  // 最后,它会调用 `firstToken` 方法来返回词素流的第一个词素。
  return firstToken();
}
类属性
- 
tokenStart:- 表示下一个将被创建的词素的字符串偏移量。
- 在 Utf8BytesScanner中,stringOffset和scanOffset的值是不同的,因为一个字符串字符可以使用多个 UTF-8 字节进行编码。
- 初始值为 -1,表示还没有开始扫描
- int类型
 
- 
tokens:- 表示由这个扫描器创建的词素流。
- 第一个词素是一个特殊的词素,它不是源文件的一部分,这是为了避免在扫描器中的特殊情况。
- 这个词素不会暴露给扫描器的客户端,客户端应该调用 firstToken方法来访问词素流。
- Token类型
 
- 
tail:- 表示最后扫描的词素。
- 这个属性是使用 late关键字声明的,表示它将在稍后进行初始化。
- Token类型
 
本文作者:Maeiee
本文链接:Dart _fe_analyzer_shared scanner AbstractScanner tokenize
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!
